package com.ruoyi.business.interceptor;

import cn.hutool.json.JSONUtil;
import com.ruoyi.business.common.Result;
import com.ruoyi.business.entity.redis.UserObj;
import com.ruoyi.business.utils.RedisConstant;
import com.ruoyi.business.utils.UserObjHolder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.concurrent.TimeUnit;

import static com.ruoyi.business.utils.RedisConstant.LOGIN_SELLER_TTL;
import static com.ruoyi.business.utils.RedisConstant.LOGIN_USER_TTL;

public class LoginInterceptor implements HandlerInterceptor {


    private StringRedisTemplate stringRedisTemplate;

    public LoginInterceptor( StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate=stringRedisTemplate;
    }


    public LoginInterceptor() {
    }


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");

        //1,获取请求头中的token
        String token = request.getHeader("token");

        String requestURI = request.getRequestURI();

        if (isErrorUrl(request.getRequestURI())) {
            // 如果请求的 URL 不是用户类型的 URL，拒绝访问
            Result<Object> objectResult = Result.route("请求与后端冲突导致/error请求");
            response.getWriter().write(JSONUtil.toJsonStr(objectResult));
//                response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Forbidden");
            return false;
        }
        if (token == null) {
            Result<Object> objectResult = Result.notLogin("未登录，请先登录");
            response.getWriter().write(JSONUtil.toJsonStr(objectResult));
            return false;
        }
        //2.获取redis中的用户信息
        String key = RedisConstant.LOGIN_USER_KEY + token;

        String userJson = stringRedisTemplate.opsForValue().get(key);
        //3.判断用户是否存在
        if (userJson == null) {
            Result<Object> objectResult = Result.notLogin("未登录，请先登录");
            response.getWriter().write(JSONUtil.toJsonStr(objectResult));
            return false;
        }

        //5.存在，保存用户信息到ThreadLocal
        //将json转为对象存储到ThreadLocal
        UserObj userObj = JSONUtil.toBean(userJson, UserObj.class);





        if (userObj.getType().equals("user")) { //是用户
            if (!isUserUrl(request.getRequestURI())) {
                // 如果请求的 URL 不是用户类型的 URL，拒绝访问
                Result<Object> objectResult = Result.route("权限验证不通过，拒绝访问");
                response.getWriter().write(JSONUtil.toJsonStr(objectResult));
//                response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Forbidden");
                return false;
            }

            //6,刷新token的有效期--String类型
            stringRedisTemplate.expire(key, LOGIN_USER_TTL, TimeUnit.MINUTES);
        } else { //是商家
            if (!isSellerUrl(request.getRequestURI())) {
                // 如果请求的 URL 不是商家类型的 URL，拒绝访问
                Result<Object> objectResult = Result.route("权限验证不通过，拒绝访问");
                response.getWriter().write(JSONUtil.toJsonStr(objectResult));
                return false;
            }
            //6,刷新商家token的有效期--String类型
            stringRedisTemplate.expire(key, LOGIN_SELLER_TTL, TimeUnit.MINUTES);
        }


        //7.放行
        UserObjHolder.saveUserObj(userObj);
        return true;
    }

    private boolean isUserUrl(String url) {
        // 根据实际业务逻辑判断 URL 是否是用户类型的 URL
        // 例如，可以根据 URL 的前缀或者特定的路径来判断
        return url.startsWith("/business/user/");
    }

    private boolean isSellerUrl(String url) {
        // 根据实际业务逻辑判断 URL 是否是商家类型的 URL
        // 例如，可以根据 URL 的前缀或者特定的路径来判断
        return url.startsWith("/business/seller/");
    }


    private boolean isErrorUrl(String url) {
        // 根据实际业务逻辑判断 URL 是否是用户类型的 URL
        // 例如，可以根据 URL 的前缀或者特定的路径来判断
        return url.startsWith("/error");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //防止内存泄漏
        UserObjHolder.removeUserObj();
    }
}
